package com.zzb.framework.query;

import com.baomidou.mybatisplus.annotations.TableField;
import com.zzb.framework.utils.ReflectionUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.RowMapper;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;

/**
 * 通过注解@Column映射字段
 * Created by zhangzhenbin on 2016/12/13.
 */
public class AnnotationColumnRowMapper<T> implements RowMapper<T> {
    private static final Logger logger = LoggerFactory.getLogger(AnnotationColumnRowMapper.class);
    /**
     * 获取T的基本类型
     */
    private Class<T> clazz;

    public AnnotationColumnRowMapper(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public T mapRow(ResultSet rs, int rowNum) throws SQLException {
        Class<T> tClazz = clazz;
        T t;
        try {
            t = tClazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            throw new SQLException("返回对象实例化失败，请确认有默认构造方法", e);
        }
        Field[] declaredFields = ReflectionUtils.getAllDeclaredFields(clazz);

        for (Field declaredField : declaredFields) {
            if ((declaredField.getModifiers() & Modifier.TRANSIENT) != 0) continue;

            Class<?> type = declaredField.getType();
            String fieldName = declaredField.getName();
            String columnName = fieldName;//数据库字段名默认是属性名
            //如果有定义@Column注解，则使用注解定义的column.name()
            TableField column = declaredField.getAnnotation(TableField.class);
            if (column != null) {
                columnName = column.value();
            }

            try {
                if (rs.getObject(columnName) == null) {
                    continue;
                }
                if (type.equals(BigDecimal.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getBigDecimal(columnName));
                } else if (type.equals(String.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getString(columnName));
                } else if (type.equals(Integer.class) || type.equals(int.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getInt(columnName));
                } else if (type.equals(Long.class) || type.equals(long.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getLong(columnName));
                } else if (type.equals(Float.class) || type.equals(float.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getFloat(columnName));
                } else if (type.equals(Double.class) || type.equals(double.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getDouble(columnName));
                } else if (type.equals(Date.class)) {
                    BeanUtils.setProperty(t, fieldName, DateTime.parse(rs.getTimestamp(columnName).toLocalDateTime().toString()).toDate());
                } else if (type.equals(java.sql.Date.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getDate(columnName));
                } else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getBoolean(columnName));
                } else if (type.equals(Byte.class) || type.equals(byte.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getByte(columnName));
                } else if (type.equals(Timestamp.class)) {
                    BeanUtils.setProperty(t, fieldName, rs.getTimestamp(columnName));
                } else if (type.equals(Serializable.class)){
                    BeanUtils.setProperty(t, fieldName, rs.getObject(columnName));
                } else {
                    throw new Exception("字段类型[" + type.getName() + "]对应失败，请联系作者");
                }
            } catch (Exception e) {
                logger.debug("字段名["+fieldName+"]字段类型[" + type.getName() + "]对应失败，请联系作者");
            }

        }

        return t;
    }
}
